/**
 * Copyright 2009 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.sapien.model;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

/**
 * Discussion entity data model.  A discussion is the second level of organization.
 * @author Adam
 * @version $Id: Discussion.java 28 2009-08-25 02:33:12Z a.ruggles $
 * 
 * Created on Feb 8, 2009 at 10:33:09 PM 
 */
@javax.persistence.Entity @Table(name = "sapien_discussions")
@NamedQueries({
	@NamedQuery(name = "discussion.listAll", query = "FROM com.google.code.sapien.model.Discussion"),
	@NamedQuery(name = "discussion.getCount", query = "SELECT COUNT(d) FROM com.google.code.sapien.model.Discussion d"),
	@NamedQuery(name = "discussion.getCountCategoryId",
			query = "SELECT COUNT(d) FROM com.google.code.sapien.model.Discussion d WHERE d.category.id = :categoryId"),
	@NamedQuery(name = "discussion.list",
			query = "FROM com.google.code.sapien.model.Discussion d ORDER BY d.modified DESC"),
	@NamedQuery(name = "discussion.listCategoryId",
			query = "FROM com.google.code.sapien.model.Discussion d "
				+ "WHERE d.category.id = :categoryId ORDER BY d.modified DESC")
})
public class Discussion implements Comparable<Discussion>, Serializable {
    /**
	 * Serial Version UID.
	 */
	private static final long serialVersionUID = -8155932358780064356L;

	/**
     * The category this discussion is organized under.
     */
    private Category category;

    /**
     * The date and time the discussion was created.
     */
    private Date created;

	/**
     * User that created this discussion.
     */
    private User creator;

    /**
     * Unique identifier.
     */
    private Long id;

    /**
     * The data and time of the last response for this discussion was created.
     */
    private Date modified;

    /**
     * The last user to add a new response to this discussion.
     */
    private User modifier;

    /**
     * The first response for this discussion.
     */
    private Response response;

    /**
     * The number of responses under this discussion.
     */
    private Integer responseCount;

	/**
     * The subject of the discussion.
     */
    private String subject;

	/**
     * The version for optimistic concurrency control.
     */
    private Integer version;

    /**
     * Adds 1 to the response count.
     */
    public void addToResponseCount() {
    	this.responseCount++;
    }

    /**
	 * {@inheritDoc}
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	public int compareTo(final Discussion comparison) {
		int value = -1;
		if (this.modified != null && comparison != null && comparison.getModified() != null) {
			value = this.modified.compareTo(comparison.getModified());
		}
		return value;
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (!(obj instanceof Discussion)) {
			return false;
		}
		final Discussion rhs = (Discussion) obj;
		return new EqualsBuilder()
			.append(subject, rhs.getSubject())
			.append(created, rhs.getCreated())
			.isEquals();
	}

	/**
	 * Returns category.
	 * @return the category.
	 */
	@ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id")
	public Category getCategory() {
		return category;
	}

	/**
	 * Returns created.
	 * @return the created.
	 */
	@Basic(optional = false) @Temporal(TemporalType.TIMESTAMP)
	public Date getCreated() {
		return created;
	}

	/**
	 * Returns creator.
	 * @return the creator.
	 */
	@ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "creator_id")
	public User getCreator() {
		return creator;
	}

	/**
	 * Returns id.
	 * @return the id.
	 */
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
	public Long getId() {
		return id;
	}

	/**
	 * Returns modified.
	 * @return the modified.
	 */
	@Basic(optional = false) @Temporal(TemporalType.TIMESTAMP)
	public Date getModified() {
		return modified;
	}

	/**
	 * Returns modifier.
	 * @return the modifier.
	 */
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "modifier_id")
	public User getModifier() {
		return modifier;
	}

	/**
	 * Returns the first response that represents the body of the discussion.
	 * @return the response.
	 */
	@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "first_response_id")
	public Response getResponse() {
		return response;
	}

	/**
	 * Returns responseCount.
	 * @return the responseCount.
	 */
    @Basic(optional = false)
	public Integer getResponseCount() {
		return responseCount;
	}

	/**
	 * Returns subject.
	 * @return the subject.
	 */
	@Column(length = 100)
	public String getSubject() {
		return subject;
	}

	/**
	 * Returns version.
	 * @return the version.
	 */
	@Version
	public Integer getVersion() {
		return version;
	}

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		return new HashCodeBuilder(41, 3)
			.append(subject)
			.append(created)
			.toHashCode();
	}

	/**
	 * Sets category.
	 * @param category the category to set.
	 */
	public void setCategory(final Category category) {
		this.category = category;
	}

	/**
	 * Sets created.
	 * @param created the created to set.
	 */
	public void setCreated(final Date created) {
		this.created = created;
	}

	/**
	 * Sets creator.
	 * @param creator the creator to set.
	 */
	public void setCreator(final User creator) {
		this.creator = creator;
	}

	/**
	 * Sets id.
	 * @param id the id to set.
	 */
	public void setId(final Long id) {
		this.id = id;
	}

	/**
	 * Sets modified.
	 * @param modified the modified to set.
	 */
	public void setModified(final Date modified) {
		this.modified = modified;
	}

	/**
	 * Sets modifier.
	 * @param modifier the modifier to set.
	 */
	public void setModifier(final User modifier) {
		this.modifier = modifier;
	}

	/**
	 * Sets the first response that represents the body of the discussion.
	 * @param response the response to set.
	 */
	public void setResponse(final Response response) {
		this.response = response;
	}

	/**
	 * Sets responseCount.
	 * @param responseCount the responseCount to set.
	 */
	public void setResponseCount(final Integer responseCount) {
		this.responseCount = responseCount;
	}

	/**
	 * Sets subject.
	 * @param subject the subject to set.
	 */
	public void setSubject(final String subject) {
		this.subject = StringUtils.abbreviate(subject, 100);
	}

	/**
	 * Sets version.
	 * @param version the version to set.
	 */
	public void setVersion(final Integer version) {
		this.version = version;
	}

	/**
     * Subtracts 1 from the response count.
     */
    public void subtractFromResponseCount() {
    	this.responseCount--;
    }

	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return new ToStringBuilder(this)
			.append("id", id)
			.append("subject", subject)
			.append("created", created)
			.append("modified", modified)
			.append("responses", responseCount)
			.append("version", version)
			.toString();
	}
}
